package com.bolt.auth.security.admin.biz.sys.service;


import com.bolt.auth.admin.api.sys.dto.PrivilegeDTO;
import com.bolt.auth.admin.api.sys.dto.PrivilegeQueryCriteria;
import com.bolt.auth.admin.api.sys.dto.converter.PrivilegeConverter;
import com.bolt.auth.admin.api.sys.entity.PrivilegeEntity;
import com.bolt.auth.admin.api.sys.entity.RoleEntity;
import com.bolt.auth.security.admin.biz.sys.repository.PrivilegeRepository;
import com.bolt.common.collection.IteratorUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.convention.exception.ServiceException;
import com.bolt.support.base.service.BaseTreeService;
import com.bolt.support.spring.jpa.repository.BasicJpaRepository;
import com.bolt.support.spring.jpa.specification.QueryHelp;
import com.bolt.support.ui.tree.vo.UITreeNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class PrivilegeService extends BaseTreeService <PrivilegeEntity, String> {


    @Autowired
    private PrivilegeRepository privilegeRepository;


    @Override
    protected BasicJpaRepository <PrivilegeEntity, String> getRepository() {
        return privilegeRepository;
    }

    @Transactional(rollbackFor = Exception.class)
    public PrivilegeEntity saveOrUpdate(PrivilegeDTO privilegeDTO) {
        PrivilegeEntity entity = PrivilegeConverter.toEntity(privilegeDTO);
        if(entity.isNew() && entity.getId().equals("0")){
            throw new ServiceException("一级目录请从菜单管理导入");
        }
        if(entity.isNew() && StrUtil.isNotBlank(entity.getPid())){
            Optional<PrivilegeEntity> parent = this.findOne(entity.getPid());
            if(parent.isPresent()){
                entity.setMenuId(parent.get().getMenuId());
            }
        }
        return save(entity);
    }

    public List <PrivilegeEntity> queryPrivilege(PrivilegeQueryCriteria criteria) {
        Sort sort = Sort.by(Sort.Direction.ASC, "orderRank");
        List <PrivilegeEntity> orgEntities = privilegeRepository
                .findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), sort);
        return orgEntities;
    }

    public List <PrivilegeEntity> findAllCached() {
        return privilegeRepository.findAllCached();
    }


    public List <PrivilegeEntity> findButtonPrivilege(Long menuId) {
        return privilegeRepository.findPrivileges(menuId, PrivilegeEntity.PrivilegeTypeEnum.BUTTON);
    }

    public PrivilegeEntity findUrlPrivilege(Long menuId) {
        List <PrivilegeEntity> privilegeEntities = privilegeRepository.findPrivileges(menuId, PrivilegeEntity.PrivilegeTypeEnum.URL);
        return IteratorUtil.isNotEmpty(privilegeEntities) ? privilegeEntities.get(0) : null;
    }

    public List <PrivilegeEntity> findPrivileges(String roleId) {
        return privilegeRepository.findPrivileges(roleId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateRelatedRoleR2s(String id, String[] roleIds) {
        PrivilegeEntity entity = privilegeRepository.getOne(id);
        updateRelatedR2s(entity, roleIds, "roleR2Privileges", "role");
    }

    public List <PrivilegeEntity> findPrivilegeByMenuId(Long[] menuIds) {
        return privilegeRepository.findPrivilegeByMenuId(menuIds);
    }

    public List <String> findIdsBymenuIds(Long[] menuIds, PrivilegeEntity.PrivilegeTypeEnum type) {
        return privilegeRepository.findPrivilegeIdsByMenuId(menuIds, type);
    }

    public List <String> findIdsByMenuIds(Long[] menuIds) {
        return privilegeRepository.findPrivilegeIdsByMenuId(menuIds);
    }


    public List <PrivilegeEntity> findPrivileges(Set <String> roleCodes) {
        return privilegeRepository.findPrivileges(roleCodes);
    }
    public List <PrivilegeEntity> findPrivileges(List <RoleEntity> roleEntities) {
        Set<String> roleIds = roleEntities.stream().map(k->k.getId()).collect(Collectors.toSet());
        return privilegeRepository.findPrivileges(roleIds);
    }


    @Override
    protected void converterTreeNode(PrivilegeEntity entity, UITreeNode treeNode) {
        super.converterTreeNode(entity, treeNode);
        treeNode.setPId(String.valueOf(entity.getPid()));
        treeNode.setTitle(entity.getTitle());
    }


    public List <PrivilegeEntity> getChildMenus(List <PrivilegeEntity> menuList, List <PrivilegeEntity> privilegeEntities) {
        for (PrivilegeEntity entity : menuList) {
            privilegeEntities.add(entity);
            List <PrivilegeEntity> menus = this.findChildren(entity);
            if (menus != null && menus.size() != 0) {
                getChildMenus(menus, privilegeEntities);
            }
        }
        return privilegeEntities;
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<PrivilegeEntity> entities){
        privilegeRepository.deleteAll(entities);
    }
}
